package junior.util.address;

import java.util.Arrays;
import java.util.EnumSet;
import java.util.Set;

/**
 * 地址词性
 * 
 * @author ZhangXiaoye
 * @date 2016年11月1日 下午4:46:26
 */
public enum AddressTokenLevel {
	
	/** 国 */
	COUNTRY(2, 2.00),
	/** 省 */
	PROVINCE(2.5, 2.00, "省", "自治区"),
	/** 市 */
	CITY(2.5, 2.00, "市", "自治州"),
	/** 区、县 */
	DISTRICT(2.5, 2.00, "区", "新区", "城区", "县", "自治县", "自治旗"),
	/** 乡、镇 */
	TOWN(2.5, 2.00, "乡", "民族乡", "镇"),
	/** 街道 */
	STREET(2, 2.00, "街道"),
	/** 路 */
	ROAD(2.45, 2.00, "街", "大街", "路", "公路", "大道", "东路", "西路", "南路", "北路", "中路"),
	/** 号、弄 */
	NUBMER(3, 2.00, "号", "弄", "号楼", "楼", "座"),
	/** 小区 */
	BUILDING(3, 3.00, "宅", "村", "新村", "城", "新城", "园", "亭", "花园", "泾", "桥", "河", "浜", "新都", "堤", "家园", "居", "坊", "人家", "园区", "队", "庭", "苑", "邸", "医院", "医学院", "饭店", "酒店", "宾馆", "责任有限公司", "有限责任公司", "有限公司", "公司", "学院", "院", "中心", "中学", "大学", "小学", "校区", "家园", "别墅", "华庭", "大厦", "工业区", "贸易城", "小区", "公寓", "广场"),
	/** 室 */
	ROOM_NUM(3, 2.00, "室"),
	/** NA */
	UNKNOW(-2, 2.00),

	;
	
	static final AddressTokenLevel[] ROUTING = {
		COUNTRY, PROVINCE, CITY, CITY, DISTRICT, DISTRICT, TOWN, TOWN, STREET, ROAD, ROAD, ROAD, NUBMER, NUBMER, BUILDING, NUBMER, ROOM_NUM
	};
	
	static final Set<AddressTokenLevel> FUZZY = EnumSet.of(COUNTRY, PROVINCE, CITY, DISTRICT, TOWN);
	
	
	final String[] suffixs;
	
	private final double[] lengthProb;
	
	private AddressTokenLevel(double mean, double sigma, String... suffixs){
		this.suffixs = suffixs;
		Arrays.sort(this.suffixs);
		this.lengthProb = new double[32];
		this.lengthProb[0] = gaussian(48, mean, sigma);
		for(int i = 1; i < this.lengthProb.length; i ++){
			this.lengthProb[i] = gaussian(i, mean, sigma);
		}
	}
	
	public double getLengthProb(int length){
		if(length < 1){
			return 0;
		}else if(length >= lengthProb.length){
			return lengthProb[0];
		}else{
			return lengthProb[length];
		}
	}
	
	private static double gaussian(double v, double mean, double sigma){
		double main = Math.exp(Math.pow(v - mean, 2) / (-2 * Math.pow(sigma, 2)));
		double base = 1.0 / (sigma * 2.50663);
		return base * main;
	}
	
	public static Integer isPossibleRouting(int level, AddressTokenLevel test){
		for(int i = level + 1; i < ROUTING.length; i ++){
			if(ROUTING[i].equals(test)){
				return i;
			}
		}
		return null;
	}
	
	public static boolean isFuzzy(AddressTokenLevel l){
		return FUZZY.contains(l);
	}
	
}
